package com.du.method;

import com.du.config.MapInfo;
import com.du.entity.ColumnInfo;
import com.du.entity.ConvertParam;
import com.du.entity.MysqlInfo;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Desc :
 * @Author: shuangdu
 * @date : 2021/3/30
 */
public class MysqlConvertJavaBean extends MysqlConvert implements ConvertMethod {

    private Map<String, String> map;


    private void initMap() {
        this.map = new HashMap<>();
        Class<MysqlInfo> infoClass = MysqlInfo.class;
        Field[] fields = infoClass.getDeclaredFields();
        for (Field f : fields) {
            if (f.isAnnotationPresent(MapInfo.class)) {
                MapInfo annotation = f.getAnnotation(MapInfo.class);
                map.put(annotation.sign(), f.getName());
            }
        }
    }


    /**
     * 实体类模板
     * @return
     */
    private String template() {
        String t =
                "public class @a {\n" +
                "@b" +
                "}\n";
        return t;
    }

    /**
     * 字段注释
     * @param comment
     * @return
     */
    private String addNote(String comment) {
        String note =
                "\t/**\n"+
                "\t * " + comment + "\n"+
                "\t */\n";
        return note;
    }

    /**
     * 驼峰命名
     * @param underscoreWord
     * @return
     */
    private String toCamelCase(String underscoreWord) {
        String[] split = underscoreWord.split("_");
        StringBuilder sb = new StringBuilder();
        for (int i = 0 ; i < split.length; i++) {
            if (i == 0) {
                sb.append(split[i]);
            } else {
                sb.append(upperCaseFirstWord(split[i]));
            }
        }
        return sb.toString();
    }

    private String upperCaseFirstWord(String word) {
        return word.substring(0, 1).toUpperCase().concat(word.substring(1));
    }

    @Override
    public String parse(MysqlInfo info) {
        // 模板需要于注解字段对应
        String template = this.template();
        // 注解字段
        Set<String> keys = map.keySet();
        for (String key : keys) {
            if (template.contains(key)) {
                Class<? extends MysqlInfo> infoClass = info.getClass();
                String fieldName = map.get(key);
                try {
                    Object obj = infoClass.getMethod("get"+ fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1))
                            .invoke(info);

                    // 这里暂时根据类型区分类名 和 字段名
                    // string 对应 类名
                    if (obj instanceof String) {
                        template = template.replaceAll(key, upperCaseFirstWord(toCamelCase(obj.toString())));
                    }
                    // list 对应 字段名
                    if (obj instanceof List) {
                        // 字段
                        StringBuilder sb = new StringBuilder();
                        List<ColumnInfo> columns = info.getColumns();
                        columns.forEach(i -> {
                            sb.append(addNote(i.getColumnComment() == null || "".equals(i.getColumnComment()) ? i.getColumnName() : i.getColumnComment()))
                                    .append("\t")
                                    .append("private ")
                                    // 匹配类型
                                    .append(i.getColumnJavaTypeSimpleName())
                                    .append(" ")
                                    .append(toCamelCase(i.getColumnName()))
                                    .append(";\n");
                        });
                        template = template.replaceAll(key, sb.toString());
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return template;
    }

    @Override
    public String parse() {
        ConvertParam param = ConvertContext.holder.getParam();
        initialize(param.getSourceText(), param.getTemplateText());
        initMap();
        return parse(generateInfo());
    }
}
